#include "log.h"
#include "global.h"
#include "cdevicectrl.h"

CDebugLog g_DebugLog;

PSDLMODULE SdlModuleInit(uint32_t u32WindowId, int s32WindowWidth, int s32WindowHeight, int s32YuvWidth, int s32YuvHeight,
                         int s32Frequency, int s32Format, int s32Channel, int volume)
{
    char as8WindowId[64];
    PSDLMODULE ptSdlModule = (PSDLMODULE)malloc(sizeof(SDLMODULE));
    do
    {
        g_DebugLog.DebugLog("SdlModuleInit  begin!  args:\n"
                            "s32WindowWidth=%d, s32WindowHeight=%d,\n"
                            "s32YuvWidth=%d, s32YuvHeight=%d,\n"
                            "frequency=%d, format=0x%x, channel=%d\n"
                            "volume=%d", s32WindowWidth, s32WindowHeight, s32YuvWidth, s32YuvHeight,
                            s32Frequency, s32Format, s32Channel, volume);
        if(NULL == ptSdlModule)
        {
            break;
        }
        memset(ptSdlModule, 0, sizeof(SDLMODULE));
        if(-1 == SDL_Init(SDL_INIT_EVENTTHREAD))
        {
            g_DebugLog.DebugLog("SdlModuleInit  SDL_Init failed:%s", SDL_GetError());
            break;
        }
        if(0 != u32WindowId)
        {
            memset(as8WindowId, 0, 64);
            sprintf(as8WindowId, "SDL_WINDOWID=0x%lx",  (long unsigned int)u32WindowId);
            SDL_putenv(as8WindowId);
        }
        //atexit(SDL_Quit);
        ptSdlModule->ptSdlWindow = SDL_SetVideoMode(s32WindowWidth, s32WindowHeight, 0, /*SDL_DOUBLEBUF | SDL_HWSURFACE|*/ SDL_SWSURFACE | SDL_ANYFORMAT);
        if(NULL == ptSdlModule->ptSdlWindow)
        {
            break;
        }
        ptSdlModule->s32WindowWidth = s32WindowWidth;
        ptSdlModule->s32WindowHeight = s32WindowHeight;
        if(0 != s32YuvWidth && 0 != s32YuvHeight)
        {
            ptSdlModule->s32YuvWidth = s32YuvWidth;
            ptSdlModule->s32YuvHeight = s32YuvHeight;
        }
        ptSdlModule->pu8BufferDecodeV = (unsigned char *)av_malloc(s32YuvWidth * s32YuvHeight * 3 / 2);
        if(NULL == ptSdlModule->pu8BufferDecodeV)
        {
            break;
        }
        ptSdlModule->pFrame = avcodec_alloc_frame();
//        int len = avpicture_get_size(PIX_FMT_YUV420P, _DISPLAY_WIDTH, _DISPLAY_HEIGHT);
//        uint8_t *pu8Temp = (uint8_t *)av_malloc(len);
//        avpicture_fill((AVPicture *)ptSdlModule->pFrame, pu8Temp, PIX_FMT_YUV420P,
//                       _CAPTURE_WIDTH, _CAPTURE_HEIGHT);
        ptSdlModule->ptSwsContextV = sws_getCachedContext(NULL, _CAPTURE_WIDTH, _CAPTURE_HEIGHT,
                                                          PIX_FMT_YUV420P, s32YuvWidth, s32YuvHeight, PIX_FMT_YUV420P,
                                                          SWS_BICUBIC, NULL, NULL, NULL);
        if(NULL == ptSdlModule->ptSwsContextV)
        {
            break;
        }

        if(0 != s32Frequency && 0 != s32Format && 0 != s32Channel)
        {
            ptSdlModule->s32Volume = volume;
            ptSdlModule->pvCallBackAudio = NULL;
            ptSdlModule->pvUserDataAudio = NULL;
            ptSdlModule->pu8BufferAudio = (uint8_t *)malloc(SDL_MAX_BUFFER_OF_SOUNDS);
            if(NULL == ptSdlModule->pu8BufferAudio)
            {
                break;
            }
            memset(ptSdlModule->pu8BufferAudio, 0, sizeof(SDL_MAX_BUFFER_OF_SOUNDS));
            memset(&ptSdlModule->tSdlAudioSpec, 0, sizeof(SDL_AudioSpec));
            ptSdlModule->tSdlAudioSpec.freq = s32Frequency;
            ptSdlModule->tSdlAudioSpec.format = s32Format;
            ptSdlModule->tSdlAudioSpec.channels = s32Channel;
            ptSdlModule->tSdlAudioSpec.samples = 0;
            ptSdlModule->tSdlAudioSpec.callback = SdlAudioMixer;
            ptSdlModule->tSdlAudioSpec.userdata = (void *)ptSdlModule;

//                setenv("SDL_AUDIODRIVER", "alsa", 1);
//                setenv("AUDIODEV", "plughw:0,3", 1);

            if(0 > SDL_OpenAudio(&ptSdlModule->tSdlAudioSpec, NULL))
            {
                g_DebugLog.DebugLog("SdlModuleInit  SDL_OpenAudio failed:%s", SDL_GetError());
                break;
            }
            ptSdlModule->hAudioSemHandle = SemaphoreCreate();
            if(NULL == ptSdlModule->hAudioSemHandle)
            {
                break;
            }
            ptSdlModule->pu8AudioFifo = (uint8_t *)FifoBufferCreate(SDL_MAX_BUFFER_OF_SOUNDS);
            if(NULL == ptSdlModule->pu8AudioFifo)
            {
                break;
            }
            ptSdlModule->cap_flag=  1;
        }
        g_DebugLog.DebugLog("SdlModuleInit success.");
        return ptSdlModule;
    }while(0);
    if(NULL != ptSdlModule)
    {
        if(NULL != ptSdlModule->pu8BufferDecodeV)
        {
            av_free(ptSdlModule->pu8BufferDecodeV);
            ptSdlModule->pu8BufferDecodeV = NULL;
        }
        if(SDL_AUDIO_PLAYING == SDL_GetAudioStatus() || SDL_AUDIO_PAUSED == SDL_GetAudioStatus())
        {
            SDL_CloseAudio();
        }
        if(NULL != ptSdlModule->pu8BufferAudio)
        {
            free(ptSdlModule->pu8BufferAudio);
            ptSdlModule->pu8BufferAudio = NULL;
        }
        if(NULL != ptSdlModule->ptYuvLayer)
        {
            SDL_FreeYUVOverlay(ptSdlModule->ptYuvLayer);
            ptSdlModule->ptYuvLayer = NULL;
        }
        if(NULL != ptSdlModule->pFrame)
        {
//            if(NULL != ptSdlModule->pFrame->data[0])
//            {
//                av_free(ptSdlModule->pFrame->data[0]);
//            }
            av_free(ptSdlModule->pFrame);
            ptSdlModule->pFrame = NULL;
        }
        if(NULL != ptSdlModule->ptSwsContextV)
        {
            sws_freeContext(ptSdlModule->ptSwsContextV);
            ptSdlModule->ptSwsContextV = NULL;
        }
        if(NULL != ptSdlModule->hAudioSemHandle)
        {
            SemaphoreDestroy(ptSdlModule->hAudioSemHandle);
            ptSdlModule->hAudioSemHandle = NULL;
        }
        if(NULL != ptSdlModule->pu8AudioFifo)
        {
            FifoBufferDestroy(ptSdlModule->pu8AudioFifo);
            ptSdlModule->pu8AudioFifo = NULL;
        }
        free(ptSdlModule);
        ptSdlModule = NULL;
    }
    SDL_Quit();
    g_DebugLog.DebugLog("SdlModuleInit failed.");
    return NULL;
}


void SdlModuleUnInit(PSDLMODULE ptSdlModule)
{
    if(NULL != ptSdlModule)
    {
        g_DebugLog.DebugLog("SdlModuleUnInit begin.");
        if(NULL != ptSdlModule->pu8BufferDecodeV)
        {
            av_free(ptSdlModule->pu8BufferDecodeV);
            ptSdlModule->pu8BufferDecodeV = NULL;
        }
        if(SDL_AUDIO_PLAYING == SDL_GetAudioStatus() || SDL_AUDIO_PAUSED == SDL_GetAudioStatus())
        {
            SDL_CloseAudio();
        }
        if(NULL != ptSdlModule->pu8BufferAudio)
        {
            free(ptSdlModule->pu8BufferAudio);
            ptSdlModule->pu8BufferAudio = NULL;
        }
        if(NULL != ptSdlModule->pu8AudioFifo)
        {
            FifoBufferDestroy(ptSdlModule->pu8AudioFifo);
            ptSdlModule->pu8AudioFifo = NULL;
        }
        if(NULL != ptSdlModule->ptYuvLayer)
        {
            SDL_FreeYUVOverlay(ptSdlModule->ptYuvLayer);
            ptSdlModule->ptYuvLayer = NULL;
        }
        if(NULL != ptSdlModule->pFrame)
        {
//            if(NULL != ptSdlModule->pFrame->data[0])
//            {
//                av_free(ptSdlModule->pFrame->data[0]);
//            }
            av_free(ptSdlModule->pFrame);
            ptSdlModule->pFrame = NULL;
        }
        if(NULL != ptSdlModule->hAudioSemHandle)
        {
            SemaphoreDestroy(ptSdlModule->hAudioSemHandle);
            ptSdlModule->hAudioSemHandle = NULL;
        }
        if(NULL != ptSdlModule->ptSwsContextV)
        {
            sws_freeContext(ptSdlModule->ptSwsContextV);
            ptSdlModule->ptSwsContextV = NULL;
        }
        free(ptSdlModule);
        ptSdlModule = NULL;
        g_DebugLog.DebugLog("SdlModuleUnInit end.");
    }
    SDL_Quit();
}


PTAVSDLYUVSURFACE AvSDLYUVCreate(PSDLMODULE ptSdlModule,
                                 int s32DisplayX, int s32DisplayY, int s32DisplayWidth, int s32DisplayHeight)
{
    PTAVSDLYUVSURFACE ptSDLYUVSurface = NULL;
    do
    {
        //g_DebugLog.DebugLog(EDEBUG_LEVEL_MESSAGE, "AvSDLYUVCreate  begin!  args:\n"
        //                       "s32DisplayX=%d, s32DisplayY=%d,\n"
        //                       "s32DisplayWidth=%d, s32DisplayHeight=%d",
        //                       s32DisplayX, s32DisplayY, s32DisplayWidth, s32DisplayHeight);
        if(NULL == ptSdlModule)
        {
            break;
        }
        ptSDLYUVSurface = (PTAVSDLYUVSURFACE)malloc(sizeof(TAVSDLYUVSURFACE));
        if(NULL == ptSDLYUVSurface)
        {
            break;
        }
        memset(ptSDLYUVSurface, 0, sizeof(TAVSDLYUVSURFACE));
        ptSDLYUVSurface->ptSdlModule = (PSDLMODULE)ptSdlModule;
        ptSDLYUVSurface->s32DisplayX = s32DisplayX;
        ptSDLYUVSurface->s32DisplayY = s32DisplayY;
        ptSDLYUVSurface->s32DisplayWidth = s32DisplayWidth;
        ptSDLYUVSurface->s32DisplayHeight = s32DisplayHeight;

        if(NULL == ptSDLYUVSurface->ptSdlModule->ptYuvLayer)
        {
            ptSDLYUVSurface->ptSdlModule->ptYuvLayer =
                    SDL_CreateYUVOverlay(ptSDLYUVSurface->ptSdlModule->s32YuvWidth, ptSDLYUVSurface->ptSdlModule->s32YuvHeight,
                                         SDL_YV12_OVERLAY, ptSDLYUVSurface->ptSdlModule->ptSdlWindow);
            if(NULL == ptSDLYUVSurface->ptSdlModule->ptYuvLayer)
            {
                //g_DebugLog.DebugLog(EDEBUG_LEVEL_NORMAL, "AvSDLYUVCreate SDL_CreateYUVOverlay failed:%s", SDL_GetError());
                break;
            }
        }
        //g_DebugLog.DebugLog(EDEBUG_LEVEL_ERROR, "AvSDLYUVCreate  successd!");
        return ptSDLYUVSurface;
    }while(0);
    if(NULL != ptSDLYUVSurface)
    {
        free(ptSDLYUVSurface);
        ptSDLYUVSurface = NULL;
    }
    //g_DebugLog.DebugLog(EDEBUG_LEVEL_ERROR, "AvSDLYUVCreate  failed.");
    return NULL;
}

void AvSDLYUVDestroy(void * pvHandle)
{
    PTAVSDLYUVSURFACE ptSDLYUVSurface = (PTAVSDLYUVSURFACE)pvHandle;
    if(NULL != ptSDLYUVSurface)
    {
        //g_DebugLog.DebugLog(EDEBUG_LEVEL_NORMAL, "AvSDLYUVDestroy begin.");
        if(NULL != ptSDLYUVSurface)
        {
            free(ptSDLYUVSurface);
            ptSDLYUVSurface = NULL;
        }
        //g_DebugLog.DebugLog(EDEBUG_LEVEL_NORMAL, "AvSDLYUVDestroy  end.");
    }
}

int AvSDLYUVDisplay(PTAVSDLYUVSURFACE pvHandle, uint8_t *pu8Buffer, int s32Length)
{
    PTAVSDLYUVSURFACE ptSDLYUVSurface = (PTAVSDLYUVSURFACE)pvHandle;
    SDL_Rect tDestRect;
    int s32Index = 0, Sources32Width = 0, Dests32Width = 0, Sources32Height = 0;
    uint8_t *pSourceY = NULL, *pSourceU = NULL, *pSourceV = NULL, *pDestY = NULL, *pDestU = NULL, *pDestV = NULL;

    if(NULL == ptSDLYUVSurface || NULL == pu8Buffer
       || 0 == ptSDLYUVSurface->s32DisplayWidth || 0 == ptSDLYUVSurface->s32DisplayHeight
       || 0 == ptSDLYUVSurface->ptSdlModule->s32YuvWidth || 0 == ptSDLYUVSurface->ptSdlModule->s32YuvHeight
       || s32Length != ptSDLYUVSurface->ptSdlModule->s32YuvWidth * ptSDLYUVSurface->ptSdlModule->s32YuvHeight * 3 / 2)
    {
        return 0;
    }
    Sources32Width =  ptSDLYUVSurface->ptSdlModule->s32YuvWidth;
    Sources32Height = ptSDLYUVSurface->ptSdlModule->s32YuvHeight;

    //double proportion = ((double)ptSDLYUVSurface->ptSdlModule->s32YuvHeight)/((double)ptSDLYUVSurface->ptSdlModule->s32YuvWidth);

    Dests32Width = ptSDLYUVSurface->ptSdlModule->ptYuvLayer->pitches[0];
    pSourceY = pu8Buffer;
    pSourceU = pu8Buffer + Sources32Width * Sources32Height * 5 / 4;
    pSourceV = pu8Buffer + Sources32Width * Sources32Height;
    SDL_LockSurface(ptSDLYUVSurface->ptSdlModule->ptSdlWindow);
    SDL_LockYUVOverlay(ptSDLYUVSurface->ptSdlModule->ptYuvLayer);
    pDestY = ptSDLYUVSurface->ptSdlModule->ptYuvLayer->pixels[0];
    pDestU = ptSDLYUVSurface->ptSdlModule->ptYuvLayer->pixels[1],
    pDestV = ptSDLYUVSurface->ptSdlModule->ptYuvLayer->pixels[2];
    for(s32Index = 0; s32Index < (int)Sources32Height; ++s32Index)
    {
        memcpy(pDestY+ s32Index * Dests32Width, pSourceY + s32Index * Sources32Width, Sources32Width);
    }
    Sources32Width =  Sources32Width >> 1;
    Sources32Height = Sources32Height >> 1;
    Dests32Width = ptSDLYUVSurface->ptSdlModule->ptYuvLayer->pitches[1];
    for(s32Index = 0; s32Index < (int)Sources32Height; ++s32Index)
    {
        memcpy(pDestU + s32Index * Dests32Width, pSourceU + s32Index * Sources32Width, Sources32Width);
        memcpy(pDestV + s32Index * Dests32Width, pSourceV + s32Index * Sources32Width, Sources32Width);
    }
    SDL_UnlockYUVOverlay(ptSDLYUVSurface->ptSdlModule->ptYuvLayer);
    SDL_UnlockSurface(ptSDLYUVSurface->ptSdlModule->ptSdlWindow);
    tDestRect.x = ptSDLYUVSurface->s32DisplayX;
    tDestRect.y = ptSDLYUVSurface->s32DisplayY;
    tDestRect.w = ptSDLYUVSurface->s32DisplayWidth;
    tDestRect.h = ptSDLYUVSurface->s32DisplayHeight;

    if(0 != SDL_DisplayYUVOverlay(ptSDLYUVSurface->ptSdlModule->ptYuvLayer, &tDestRect))
    {
        return 0;
    }
    return 1;
}

void AvSdlAudioStart(void * pvHandle)
{
    PSDLMODULE ptSdlAudio = (PSDLMODULE)pvHandle;
    if(NULL != ptSdlAudio && SDL_AUDIO_PLAYING != SDL_GetAudioStatus())
    {
        SDL_PauseAudio(0);
    }
    //g_DebugLog.DebugLog(EDEBUG_LEVEL_MESSAGE, "AvSdlAudioStart  ok.");
}

void AvSdlAudioStop(void * pvHandle)
{
    PSDLMODULE ptSdlAudio = (PSDLMODULE)pvHandle;
    if(NULL != ptSdlAudio && SDL_AUDIO_PLAYING == SDL_GetAudioStatus())
    {
        SDL_PauseAudio(1);
    }
    //g_DebugLog.DebugLog(EDEBUG_LEVEL_MESSAGE, "AvSdlAudioStop ok.");
}

void SdlAudioMixer(void *pvUserData, Uint8 *pu8Buffer, int s32Length)
{
    PSDLMODULE ptSdlModule = (PSDLMODULE)pvUserData;
    int s32Temp = s32Length;
    if(NULL != ptSdlModule)
    {
        SemaphoreTake(ptSdlModule->hAudioSemHandle);
        int ret = FifoBufferRead(ptSdlModule->pu8AudioFifo, pu8Buffer, &s32Length);
        SemaphoreGive(ptSdlModule->hAudioSemHandle);
        if(ret > 0)
        {
            SDL_MixAudio((Uint8 *)pu8Buffer, (Uint8 *)(ptSdlModule->pu8BufferAudio), s32Temp, ptSdlModule->s32Volume);
        }
    }
}

void *ThreadRecordPcm( void *pVoid)
{
    PSDLMODULE pSdlModule = (PSDLMODULE )pVoid;
    if(NULL == pSdlModule)
    {
        g_DebugLog.DebugLog("ThreadRecordPcm end. sdlmodule is null.");
        return NULL;
    }
    do{
        g_DebugLog.DebugLog("ThreadRecordPcm start.");
        int err;
        int capture_frame_number;
        int buffersize;
        unsigned char* buf;//[buffersize];
        snd_pcm_t *capture_handle;
        snd_pcm_hw_params_t *hw_params;
        unsigned int rate=44100;
        unsigned int channel=2;
        unsigned int bits=16;
        unsigned int recordtime=1; // 1 second
        unsigned int framesize;
        char deviceName[]="default";

        capture_frame_number=rate*recordtime/50;   //20 ms
        framesize=channel*bits/8;
        buffersize=capture_frame_number*framesize;
        buf=(unsigned char*)malloc(buffersize);
        memset(buf,0,buffersize);
        if ((err = snd_pcm_open (&capture_handle, deviceName, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
            g_DebugLog.DebugLog("cannot open audio device %s (%s)",
                                deviceName,
                                snd_strerror (err));
            return NULL;
        }
        if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
            g_DebugLog.DebugLog ("cannot allocate hardware parameter structure (%s)",
                                 snd_strerror (err));
            return NULL;
        }

        if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) {
            g_DebugLog.DebugLog("cannot initialize hardware parameter structure (%s)",
                                snd_strerror (err));
            return NULL;
        }

        if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
            g_DebugLog.DebugLog("cannot set access type (%s)",
                                snd_strerror (err));
            return NULL;
        }

        if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
            g_DebugLog.DebugLog("cannot set sample format (%s)",
                                snd_strerror (err));
            return NULL;
        }

        if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, &rate, 0)) < 0) {
            g_DebugLog.DebugLog( "cannot set sample rate (%s)",
                                 snd_strerror (err));
            return NULL;
        }
        if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, channel)) < 0) {
            g_DebugLog.DebugLog("cannot set channel count (%s)",
                                snd_strerror (err));
            return NULL;
        }

        if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) {
            g_DebugLog.DebugLog("cannot set parameters (%s)",
                                snd_strerror (err));
            return NULL;
        }

        snd_pcm_hw_params_free (hw_params);

        if ((err = snd_pcm_prepare (capture_handle)) < 0) {
            g_DebugLog.DebugLog("cannot prepare audio interface for use (%s)",
                                snd_strerror (err));
            return NULL;
        }
        FILE *fp = fopen("pcm.pcm", "wb");
        while(pSdlModule->cap_flag)
        {
            if ((err = snd_pcm_readi (capture_handle, buf, capture_frame_number)) != capture_frame_number) {
                g_DebugLog.DebugLog("read from audio interface failed (%s)",
                                    snd_strerror (err));
                break;
            }
            SemaphoreTake(pSdlModule->hAudioSemHandle);
            FifoBufferWrite(pSdlModule->pu8AudioFifo, buf, buffersize);
            SemaphoreGive(pSdlModule->hAudioSemHandle);
            fwrite(buf, 1, buffersize, fp);
            fflush(fp);
            memset(buf,0,buffersize);
            usleep(5000);
        }
        free(buf);
        snd_pcm_close (capture_handle);
        g_DebugLog.DebugLog("ThreadRecordPcm end. restart audio capture");
    }while(pSdlModule->cap_flag);
     pthread_detach(pthread_self());
     pthread_exit(0);
 }

void *ThreadReadAndDispaly(void *pVoid)
{
    CDeviceCtrl *pDev = (CDeviceCtrl *)pVoid;
    if(NULL == pDev)
    {
        return NULL;
    }
    g_DebugLog.DebugLog("ThreadReadAndDisplay start.");

    struct v4l2_buffer              buf;
    enum v4l2_buf_type              type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if(-1 == ioctl(pDev->GetDeviceHandle(), VIDIOC_STREAMON, &type))
    {
        g_DebugLog.DebugLog("VIDIOC_STREAMON failed.err:%s", strerror(errno));
    }

    struct timeval                  tv;
    fd_set                          fds;
    int ret(-1);
    while(pDev->GetCapFlag()){
        do {
            FD_ZERO(&fds);
            FD_SET(pDev->GetDeviceHandle(), &fds);

            /* Timeout. */
            tv.tv_sec = 2;
            tv.tv_usec = 0;

            ret = select(pDev->GetDeviceHandle() + 1, &fds, NULL, NULL, &tv);
        } while ((ret == -1 && (errno = EINTR)));
        if (ret == -1) {
            g_DebugLog.DebugLog("select failed continue.err:%s", strerror(errno));

            continue;
        }

        CLEAR(buf);
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        if(-1 == ioctl(pDev->GetDeviceHandle(), VIDIOC_DQBUF, &buf))
        {
            g_DebugLog.DebugLog("VIDIOC_DQBUF failed continue.err:%s", strerror(errno));
            continue;
        }


        avpicture_fill((AVPicture *)pDev->GetSdlModule()->pFrame, (unsigned char*)(pDev->GetVideoBuffer()[buf.index]).start,
                       PIX_FMT_YUV420P, _CAPTURE_WIDTH, _CAPTURE_HEIGHT);
        //ffmpeg swscale
        if(NULL != pDev->GetSdlModule()->ptSwsContextV)
        {
            uint8_t *pu8DestData[4] = {
                pDev->GetSdlModule()->pu8BufferDecodeV,
                pDev->GetSdlModule()->pu8BufferDecodeV + pDev->GetSdlModule()->s32YuvWidth * pDev->GetSdlModule()->s32YuvHeight,
                pDev->GetSdlModule()->pu8BufferDecodeV + pDev->GetSdlModule()->s32YuvWidth * pDev->GetSdlModule()->s32YuvHeight*5/4,
                0};
            int s32DestSlice[4] = {pDev->GetSdlModule()->s32YuvWidth, pDev->GetSdlModule()->s32YuvWidth/2,
                                   pDev->GetSdlModule()->s32YuvWidth/2, 0};

            if(NULL != pDev->GetSurface() && sws_scale(pDev->GetSdlModule()->ptSwsContextV,
                                                       pDev->GetSdlModule()->pFrame->data, pDev->GetSdlModule()->pFrame->linesize,
                                                       0, pDev->GetSdlModule()->s32YuvHeight, pu8DestData, s32DestSlice))
            {
                AvSDLYUVDisplay(pDev->GetSurface(), pDev->GetSdlModule()->pu8BufferDecodeV,
                                pDev->GetSdlModule()->s32YuvWidth * pDev->GetSdlModule()->s32YuvHeight*3/2) ;
            }else
            {
//                AvSDLYUVDisplay(pDev->GetSurface(), (unsigned char*)(pDev->GetVideoBuffer()[buf.index]).start, buf.bytesused) ;
                g_DebugLog.DebugLog("surface is NULL or sws_scale failed.");
            }
        }
        if(-1 == ioctl(pDev->GetDeviceHandle(), VIDIOC_QBUF, &buf))
        {
            g_DebugLog.DebugLog("VIDIOC_QBUF .err:%s", strerror(errno));
            continue;
        }
    }
    g_DebugLog.DebugLog("ThreadReadAndDisplay end .");
    pthread_detach(pthread_self());
    pthread_exit(0);
}
